package mysql;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

/**
 * @ProjectName: SpringBoot_AutoDev
 * @Package: mysql
 * @ClassName: DeadlockDemo
 * @Author: LXC
 * @Description: 死锁测试
 * @Date: 2025/8/30 10:09
 */
public class DeadlockDemo {

    static String url = "jdbc:mysql://localhost:3309/local_data?useSSL=false&serverTimezone=UTC";
    static String user = "root";
    static String password = "314159";

    public static void main(String[] args) {
        Runnable task1 = () -> {
            try (Connection conn = DriverManager.getConnection(url, user, password)) {
                conn.setAutoCommit(false);

                // 锁住 id=1
                try (PreparedStatement ps = conn.prepareStatement("UPDATE account SET balance = balance - 10 WHERE id = 1")) {
                    ps.executeUpdate();
                }

                // 等待，保证另一个线程也锁住另一行
                Thread.sleep(1000);

                // 再去锁 id=2（可能会死锁）
                try (PreparedStatement ps = conn.prepareStatement("UPDATE account SET balance = balance + 10 WHERE id = 2")) {
                    ps.executeUpdate();
                }

                conn.commit();
            } catch (Exception e) {
                e.printStackTrace();
            }
        };

        Runnable task2 = () -> {
            try (Connection conn = DriverManager.getConnection(url, user, password)) {
                conn.setAutoCommit(false);

                // 锁住 id=2
                try (PreparedStatement ps = conn.prepareStatement("UPDATE account SET balance = balance - 20 WHERE id = 2")) {
                    ps.executeUpdate();
                }

                // 等待，保证另一个线程也锁住另一行
                Thread.sleep(1000);

                // 再去锁 id=1（可能会死锁）
                try (PreparedStatement ps = conn.prepareStatement("UPDATE account SET balance = balance + 20 WHERE id = 1")) {
                    ps.executeUpdate();
                }

                conn.commit();
            } catch (Exception e) {
                e.printStackTrace();
            }
        };

        // 启动两个线程
        new Thread(task1).start();
        new Thread(task2).start();
    }
}
